/*
依次使用
new、malloc、calloc、realloc和mmap进行分配内存>=1k，并判断分配内存是否失败，
通过运行程序添加--release 参数来控制是否释放，如：./cpu_memory_test --free
*/
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>

#include <cstdlib>
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>

void print_help() {
    std::cout << "Usage: ./mem_test [options]\n"
              << "Options:\n"
              << "  --size N       Memory size in bytes for all allocations "
                 "(default: 1024)\n"
              << "  --free     Release all allocated memory\n"
              << "  --help         Show this help message\n";
    return;
}

int main(int argc, char *argv[]) {
    size_t size = 10240;
    bool free_all = false;

    // 解析命令行参数
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == "--size" && i + 1 < argc) {
            size = std::stoul(argv[++i]);
        } else if (arg == "--free") {
            free_all = true;
        } else if (arg == "--help") {
            print_help();
            return 0;
        }
    }

    // 记录所有分配的内存指针
    char *new_mem = nullptr;
    void *malloc_mem = nullptr;
    void *calloc_mem = nullptr;
    void *realloc_mem = nullptr;
    void *mmap_mem = nullptr;

    // 1. new 分配
    new_mem = new char[size];
    std::cout << "[new] Allocated: " << static_cast<void *>(new_mem) << " ("
              << size << " bytes)\n";

    // 2. malloc 分配
    malloc_mem = malloc(size);
    std::cout << "[malloc] Allocated: " << malloc_mem << " (" << size
              << " bytes)\n";

    // 3. calloc 分配
    calloc_mem = calloc(1, size);
    std::cout << "[calloc] Allocated: " << calloc_mem << " (" << size
              << " bytes)\n";

    // 4. realloc 分配（先malloc再realloc）
    void *initial_malloc = malloc(size);
    realloc_mem = realloc(initial_malloc, size); // 实际大小不变
    std::cout << "[realloc] Reallocated: " << realloc_mem << " (" << size
              << " bytes)\n";

    // 5. mmap 分配
    mmap_mem = mmap(nullptr, size, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    std::cout << "[mmap] Allocated: " << mmap_mem << " (" << size
              << " bytes)\n";

    // 统一释放内存
    if (free_all) {
        std::cout << "\nFreeing all memory:\n";
        delete[] new_mem;
        std::cout << "[new] Freed\n";

        free(malloc_mem);
        std::cout << "[malloc] Freed\n";

        free(calloc_mem);
        std::cout << "[calloc] Freed\n";

        free(realloc_mem); // 直接释放realloc后的指针
        std::cout << "[realloc] Freed\n";

        munmap(mmap_mem, size);
        std::cout << "[mmap] Freed\n";
    }

    //    std::cout << "\nValgrind command:\n"
    //              << "valgrind --leak-check=full --show-leak-kinds=all
    //              --track-origins=yes ./mem_test --size "
    //              << size << (free_all ? " --free" : "") << "\n";
    return 0;
}